/*
 * @author: wizardc
 */

using System.Text;
using Dou.ScreenController;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace DouEditor.ScreenController
{
    /// <summary>
    /// 屏幕控制管理器
    /// </summary>
    public static class ScreenControllerMgr
    {
        [InitializeOnLoadMethod]
        public static void OnEditorInit()
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;
            SceneManager.sceneLoaded += OnSceneLoaded;

            PrefabStage.prefabStageOpened -= OnPrefabLoaded;
            PrefabStage.prefabStageOpened += OnPrefabLoaded;
        }

        private static void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
        {
            var roots = scene.GetRootGameObjects();
            foreach (var root in roots)
            {
                RefreshLayout(root);
            }
        }

        private static void OnPrefabLoaded(PrefabStage prefabStage)
        {
            var root = prefabStage.prefabContentsRoot;
            RefreshLayout(root);
        }

        public static void SetLandscapeDesignWidth(int designWidth)
        {
            EditorPrefs.SetInt("UILandscapeDesignWidth", designWidth);
        }

        public static int GetLandscapeDesignWidth()
        {
            if (!EditorPrefs.HasKey("UILandscapeDesignWidth"))
            {
                return 1920;
            }
            return EditorPrefs.GetInt("UILandscapeDesignWidth");
        }

        public static void SetLandscapeDesignHeight(int designHeight)
        {
            EditorPrefs.SetInt("UILandscapeDesignHeight", designHeight);
        }

        public static int GetLandscapeDesignHeight()
        {
            if (!EditorPrefs.HasKey("UILandscapeDesignHeight"))
            {
                return 1080;
            }
            return EditorPrefs.GetInt("UILandscapeDesignHeight");
        }

        public static void SetLandscapeMatchWidthOrHeight(float matchWidthOrHeight)
        {
            EditorPrefs.SetFloat("UILandscapeMatchWidthOrHeight", matchWidthOrHeight);
        }

        public static float GetLandscapeMatchWidthOrHeight()
        {
            if (!EditorPrefs.HasKey("UILandscapeMatchWidthOrHeight"))
            {
                return 0;
            }
            return EditorPrefs.GetFloat("UILandscapeMatchWidthOrHeight");
        }
        
        public static void SetScreenMode(UIScreenMode uiScreenMode)
        {
            EditorPrefs.SetInt("UIScreenMode", (int) uiScreenMode);
        }
        
        public static UIScreenMode GetScreenMode()
        {
            if (!EditorPrefs.HasKey("UIScreenMode"))
            {
                return UIScreenMode.Landscape;
            }
            return (UIScreenMode) EditorPrefs.GetInt("UIScreenMode");
        }

        public static void SetFineTuningMode(UIFineTuningMode uiFineTuningMode)
        {
            EditorPrefs.SetInt("UIFineTuningMode", (int) uiFineTuningMode);
        }
        
        public static UIFineTuningMode GetFineTuningMode()
        {
            if (!EditorPrefs.HasKey("UIFineTuningMode"))
            {
                return UIFineTuningMode.None;
            }
            return (UIFineTuningMode) EditorPrefs.GetInt("UIFineTuningMode");
        }

        /// <summary>
        /// 编辑器状态下刷新当前场景的布局
        /// </summary>
        public static void RefreshLayout()
        {
            if (EditorApplication.isPlaying)
            {
                return;
            }
            
            var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
            if (prefabStage == null)
            {
                // 未打开预制编辑时
                for (int i = 0; i < SceneManager.loadedSceneCount; i++)
                {
                    var scene = SceneManager.GetSceneAt(i);
                    var roots = scene.GetRootGameObjects();
                    foreach (var root in roots)
                    {
                        RefreshLayout(root);
                    }
                }
            }
            else
            {
                // 打开预制编辑时
                var root = prefabStage.prefabContentsRoot;
                RefreshLayout(root);
            }
        }

        private static void RefreshLayout(GameObject root)
        {
            RefreshCanvasScaler(root);
            RefreshRectTransform(root);
            RefreshActive(root);
            RefreshHorizontalOrVerticalLayout(root);
            RefreshDTextMeshProUGUI(root);
        }

        private static void RefreshCanvasScaler(GameObject root)
        {
            var adapters = root.GetComponentsInChildren<CanvasScalerAdapter>(true);
            if (adapters.Length == 0)
            {
                return;
            }
            var uiScreenMode = GetScreenMode();
            var designWidth = GetLandscapeDesignWidth();
            var designHeight = GetLandscapeDesignHeight();
            var matchWidthOrHeight = GetLandscapeMatchWidthOrHeight();
            var referenceResolution = uiScreenMode == UIScreenMode.Landscape ? new Vector2(designWidth, designHeight) : new Vector2(designHeight, designWidth);
            if (uiScreenMode != UIScreenMode.Landscape)
            {
                matchWidthOrHeight = 1 - matchWidthOrHeight;
            }
            foreach (var adapter in adapters)
            {
                adapter.RefreshAdapterInEditor(referenceResolution, matchWidthOrHeight);
                EditorUtility.SetDirty(adapter.gameObject);
            }
        }

        private static void RefreshRectTransform(GameObject root)
        {
            var adapters = root.GetComponentsInChildren<RectTransformAdapter>(true);
            if (adapters.Length == 0)
            {
                return;
            }
            var uiScreenMode = (int) GetScreenMode();
            var uiFineTuningMode = (int) GetFineTuningMode();
            foreach (var adapter in adapters)
            {
                adapter.RefreshAdapterInEditor(uiScreenMode, uiFineTuningMode);
                EditorUtility.SetDirty(adapter.gameObject);
            }
        }

        private static void RefreshActive(GameObject root)
        {
            var adapters = root.GetComponentsInChildren<ActiveAdapter>(true);
            if (adapters.Length == 0)
            {
                return;
            }
            var uiScreenMode = (int) GetScreenMode();
            var uiFineTuningMode = (int) GetFineTuningMode();
            foreach (var adapter in adapters)
            {
                adapter.RefreshAdapterInEditor(uiScreenMode, uiFineTuningMode);
                EditorUtility.SetDirty(adapter.gameObject);
            }
        }

        private static void RefreshHorizontalOrVerticalLayout(GameObject root)
        {
            var adapters = root.GetComponentsInChildren<HorizontalOrVerticalLayoutGroupAdapter>(true);
            if (adapters.Length == 0)
            {
                return;
            }
            var uiScreenMode = (int) GetScreenMode();
            var uiFineTuningMode = (int) GetFineTuningMode();
            foreach (var adapter in adapters)
            {
                adapter.RefreshAdapterInEditor(uiScreenMode, uiFineTuningMode);
                EditorUtility.SetDirty(adapter.gameObject);
            }
        }

        private static void RefreshDTextMeshProUGUI(GameObject root)
        {
            var adapters = root.GetComponentsInChildren<DTextMeshProUGUIAdapter>(true);
            if (adapters.Length == 0)
            {
                return;
            }
            var uiScreenMode = (int) GetScreenMode();
            var uiFineTuningMode = (int) GetFineTuningMode();
            foreach (var adapter in adapters)
            {
                adapter.RefreshAdapterInEditor(uiScreenMode, uiFineTuningMode);
                EditorUtility.SetDirty(adapter.gameObject);
            }
        }

        public static void GetNowLayoutNameAndColor(out string name, out Color color)
        {
            var uiScreenMode = GetScreenMode();
            var nameSB = new StringBuilder();
            color = Color.white;
            if (uiScreenMode == UIScreenMode.Landscape)
            {
                nameSB.Append("横屏");
                color = Color.green;
            }
            else if (uiScreenMode == UIScreenMode.Portrait)
            {
                nameSB.Append("竖屏");
                color = Color.cyan;
            }
            nameSB.Append(" - ");
            var uiFineTuningMode = GetFineTuningMode();
            switch (uiFineTuningMode)
            {
                case UIFineTuningMode.None:
                    nameSB.Append("无");
                    break;
                case UIFineTuningMode.CN:
                    nameSB.Append("简中");
                    break;
                case UIFineTuningMode.TC:
                    nameSB.Append("繁中");
                    break;
                case UIFineTuningMode.EN:
                    nameSB.Append("英文");
                    break;
            }
            name = nameSB.ToString();
        }

        public static Color DrawScreenModeLabel()
        {
            var color = GUI.color;
            GetNowLayoutNameAndColor(out var name, out var col);
            GUI.color = col;
            EditorGUILayout.LabelField(name);
            GUI.color = color;
            return col;
        }
    }
}
